# ai_processing/summary_processor.py
"""
AI摘要处理模块
包含新闻摘要生成的相关功能
"""

from config import Config
import requests
import json
import logging
import time
from typing import Optional, Dict

# 配置日志
logger = logging.getLogger(__name__)

class BaiduNewsSummarizer:
    """
    百度AI新闻摘要生成器
    使用百度自然语言处理API生成中文新闻摘要

    使用步骤：
    1. 访问 https://ai.baidu.com/ 注册账号
    2. 在控制台创建应用，获取API Key和Secret Key
    3. 初始化时传入你的API凭证
    免费额度：每日500次调用
    """
    def __init__(self):
        """
        初始化摘要生成器
        """
        self.api_key = getattr(Config, "BAIDU_AI_API_KEY", '')
        self.secret_key = getattr(Config, "BAIDU_AI_SECRET_KEY", '')
        self.access_token = self._get_access_token()
        self.api_url = "https://aip.baidubce.com/rpc/2.0/nlp/v1/news_summary"
        self.last_call_time = 0
        self.request_count = 0

    def _get_access_token(self) -> str:
        """获取百度API访问令牌"""
        token_url = "https://aip.baidubce.com/oauth/2.0/token"
        params = {
            "grant_type": "client_credentials",
            "client_id": self.api_key,
            "client_secret": self.secret_key
        }

        try:
            response = requests.get(token_url, params=params, timeout=10)
            response.raise_for_status()
            result = response.json()

            if "access_token" in result:
                logger.info("成功获取百度API访问令牌")
                return result["access_token"]
            else:
                error_msg = result.get("error_description", "未知错误")
                logger.error(f"获取访问令牌失败: {error_msg}")
                raise Exception(f"百度API错误: {error_msg}")

        except requests.exceptions.RequestException as e:
            logger.error(f"网络请求失败: {str(e)}")
            raise
        except json.JSONDecodeError:
            logger.error("解析百度API响应失败")
            raise Exception("无效的API响应")

    def _rate_limit(self):
        """API调用频率限制（免费版QPS=2）"""
        current_time = time.time()
        elapsed = current_time - self.last_call_time

        # 如果执行时间小于1秒，则需要限速等待
        if elapsed < 1:
            sleep_time = 1 - elapsed
            time.sleep(sleep_time)
            logger.debug(f"API限速: 等待{sleep_time:.2f}秒")

    def summarize(self, content: str, title: str = "", max_length: int = 50) -> Optional[str]:
        """
        生成新闻摘要

        :param content: 新闻正文内容
        :param title: 新闻标题（可选）
        :param max_length: 摘要最大长度（默认200字）
        :return: 生成的摘要文本，失败时返回None
        """
        # 检查内容长度（API限制最大3000字节）
        if len(content.encode('utf-8')) > 3000:
            logger.warning("新闻内容超过3000字节限制，将进行截断")
            # 智能截断：保留前面内容，同时确保完整句子
            truncated_content = ""
            for sentence in content.split('。'):
                if len((truncated_content + sentence + '。').encode('utf-8')) <= 3000:
                    truncated_content += sentence + '。'
                else:
                    break
            content = truncated_content.strip('。') + '。'
            logger.info(f"截断后内容长度: {len(content.encode('utf-8'))}字节")

        # API限速控制
        self._rate_limit()

        # 准备请求参数
        params = {
            "access_token": self.access_token,
            "charset": "UTF-8"
        }

        payload = {
            "content": content,
            "max_summary_len": max_length
        }

        if title:
            payload["title"] = title

        headers = {"Content-Type": "application/json"}

        try:
            # 调用API
            response = requests.post(
                self.api_url,
                params=params,
                headers=headers,
                data=json.dumps(payload),
                timeout=15
            )
            response.raise_for_status()

            # 更新调用状态
            self.last_call_time = time.time()
            self.request_count += 1

            # 解析结果
            result = response.json()

            if "error_code" in result:
                error_msg = result.get("error_msg", "未知错误")
                logger.error(f"百度API返回错误: {error_msg} (错误码: {result['error_code']})")
                return None

            if "summary" in result:
                logger.info(f"成功生成摘要 (长度: {len(result['summary'])}字)")
                return result["summary"]
            else:
                logger.warning("API响应中未找到摘要内容")
                return None

        except requests.exceptions.RequestException as e:
            logger.error(f"API请求失败: {str(e)}")
            return None
        except json.JSONDecodeError:
            logger.error("解析API响应失败")
            return None

    def get_usage_info(self) -> Dict[str, int]:
        """获取API使用信息"""
        return {
            "request_count": self.request_count,
            "last_call_time": self.last_call_time
        }

def generate_board_summary(title, content):
    """
    生成看板摘要

    Args:
        title (str): 新闻标题
        content (str): 新闻内容

    Returns:
        str: 适合作为看板展示的简短摘要文本
    """
    # 确保输入是字符串
    if isinstance(title, bytes):
        title = title.decode('utf-8')
    elif not isinstance(title, str):
        title = str(title)

    if isinstance(content, bytes):
        content = content.decode('utf-8')
    elif not isinstance(content, str):
        content = str(content)

    # 尝试使用DeepSeek LLM模型生成摘要
    try:
        summary = _generate_deepseek_board_summary(title, content)
        if summary and summary != "摘要生成失败":
            logger.info("使用DeepSeek LLM生成看板摘要成功")
            return summary
    except Exception as e:
        logger.warning(f"DeepSeek LLM生成看板摘要失败: {e}")

    # 如果DeepSeek生成失败，使用原有逻辑
    max_length = getattr(Config, 'BOARD_SUMMARY_MAX_LENGTH', 15)
    ellipsis_text = getattr(Config, 'BOARD_SUMMARY_ELLIPSIS', '...')

    if len(title) <= max_length:
        return title
    else:
        # 保留空间给省略号
        return title[:max_length-len(ellipsis_text)] + ellipsis_text

def _generate_deepseek_board_summary(title, content):
    """
    使用DeepSeek LLM模型生成看板摘要

    Args:
        title (str): 新闻标题
        content (str): 新闻内容

    Returns:
        str: 生成的看板摘要
    """
    try:
        # 检查是否启用DeepSeek摘要功能
        if not getattr(Config, 'DEEPSEEK_SUMMARY_ENABLED', False):
            return None

        # 从配置获取DeepSeek相关设置
        deepseek_api_url = getattr(Config, 'DEEPSEEK_API_URL', 'https://api.deepseek.com/v1/chat/completions')
        deepseek_api_key = getattr(Config, 'DEEPSEEK_API_KEY', None)

        if not deepseek_api_key:
            logger.warning("未配置DeepSeek API密钥")
            return None

        # 导入提示词模板
        from utils.prompt_templates import BOARD_SUMMARY_TEMPLATE

        # 获取配置参数
        max_length = getattr(Config, 'BOARD_SUMMARY_MAX_LENGTH', 50)
        ellipsis_text = getattr(Config, 'BOARD_SUMMARY_ELLIPSIS', '...')

        # 构建提示词
        prompt = BOARD_SUMMARY_TEMPLATE.format(
            max_length=max_length,
            ellipsis_text=ellipsis_text,
            title=title,
            content=content
        )

        # 构建请求
        headers = {
            'Content-Type': 'application/json',
            'Authorization': f'Bearer {deepseek_api_key}'
        }

        payload = {
            "model": getattr(Config, 'DEEPSEEK_MODEL', 'deepseek-chat'),
            "messages": [
                {"role": "user", "content": prompt}
            ],
            "max_tokens": max_length + 20,  # 给一些额外的token空间
            "temperature": 0.3,  # 较低的温度以获得更确定的结果
            "stream": False
        }

        # 发送请求到DeepSeek API
        response = requests.post(
            deepseek_api_url,
            headers=headers,
            data=json.dumps(payload, ensure_ascii=False).encode('utf-8'),
            timeout=30
        )
        response.encoding = 'utf-8'

        if response.status_code == 200:
            result = response.json()

            # 解析DeepSeek API的响应
            if 'choices' in result and len(result['choices']) > 0:
                summary = result['choices'][0]['message']['content'].strip()

                if summary:
                    # 清理摘要内容，移除可能的多余格式
                    summary = summary.replace('\n', '').replace('\r', '').strip()

                    # 确保长度符合要求
                    if len(summary) > max_length:
                        summary = summary[:max_length-len(ellipsis_text)] + ellipsis_text

                    # 移除可能的标记符号
                    summary = summary.replace('"', '').replace("'", "").strip()

                    logger.info(f"DeepSeek生成看板摘要成功: {summary}")
                    return summary

            logger.warning("DeepSeek API返回空摘要")
            return None

        else:
            logger.warning(f"DeepSeek API调用失败，状态码: {response.status_code}")
            return None

    except requests.exceptions.Timeout:
        logger.warning("DeepSeek API调用超时")
        return None
    except requests.exceptions.RequestException as e:
        logger.warning(f"DeepSeek API网络请求错误: {e}")
        return None
    except Exception as e:
        logger.warning(f"DeepSeek生成摘要时发生未知错误: {e}")
        return None
